<?php
declare (strict_types = 1);

namespace app\auth\service;

use app\auth\common\util\ApiUtil;
use app\auth\model\AdminModel;
use think\facade\Cache;

class AdminService  extends BaseService
{
    public function __construct(AdminModel $adminModel,RightService $rightService,RoleRightLinkService $roleRightLinkService)
    {
        $this->adminModel = $adminModel;
        $this->rightService = $rightService;
        $this->roleRightLinkService = $roleRightLinkService;
    }

    public function model(){
        return $this->adminModel;
    }

    public function list(array $where = [] , array $limit = [], array $sort= []){
        $limit = check_limit($limit);
        $sort = check_sort($sort);
        return $this->adminModel::with([AdminModel::WITH_DEPT, AdminModel::WITH_ROLE, AdminModel::WITH_USER_INFO])
            ->where($where)
            ->limit($limit['page'],$limit['pagesize'])
            ->order($sort[0],$sort[1])
            ->select();
    }

    public function count(array $where = []){
        return $this->adminModel->where($where)->count();
    }

    public function find(array $where = [],array $field = ['*']){
        return $this->adminModel::with([AdminModel::WITH_ROLE, AdminModel::WITH_DEPT])->field($field)->where($where)->find();
    }

    public function select(array $where = [],array $field = ['*']){
        return $this->adminModel::with([AdminModel::WITH_DEPT, AdminModel::WITH_ROLE, AdminModel::WITH_USER_INFO])->where($where)->select();
    }

    public function insertGetId(array $data = []){
        return $this->adminModel->insertGetId($data);
    }

    public function update(array $where = [],array $data = []){
        return $this->adminModel->where($where)->update($data);
    }

    public function setLoginToken(int $user_id){
        //缓存键值对
        $value = uniqid("", true) . '.' . md5((string)rand(0,99999999));
        $key = 'login_token_' . $user_id;
        //过期时间
        $expires = date("Y-m-d H:i:s",strtotime("+1week",strtotime(date("Y-m-d H:i:s"))));
        //过期时间 1 周
        $expire = 24*60*60*7;
        if (!Cache::set($key, $value, $expire))  return false;
        //按照规则将用户id和值拼接成字符
        $token = base64_encode(substr(md5((string)rand(0,9)), 0, 16) . $user_id . ',' . $value);
        return ['token' => $token, 'expires' => strtotime($expires), 'expires_str' => $expires];
    }

    public function getLoginToken(string $token){
        //按照规则解密字符，获取用户id和值
        $str = base64_decode($token);
        $str_arr = explode(',', $str);
        if (count($str_arr) != 2)
            return false;
        $user_id = (int)substr($str_arr[0], 16);
        $value = $str_arr[1];
        $key = 'login_token_' . $user_id;
        //根据键值对判断token是否正确
        if (!empty($value) && !empty(Cache::get($key)) )
            return $user_id;
        else
            return false;
    }

    /**
     * 管理员登陆验证
     * @param string $token
     * @param string|null $value 权限代码（格式：模块?请求方法?路由，中间用?号连接起来），不传则不验证权限
     */
    public function checkLogin(string $token, string $value = null){
        $user_id = $this->getLoginToken($token);
        if (!$user_id)  return ApiUtil::normal( null, '登陆凭证已过期', ApiUtil::CODE_NOT_AUTH);
        //获取管理员信息
        $admin_info = $this->find(['user_id'=>$user_id],['id','role_id','type']);
        if (!$admin_info)  return ApiUtil::normal( null, '你不是管理员',ApiUtil::CODE_NOT_AUTH);
        if ($value && $admin_info['type'] != AdminModel::TYPE_SUPER){
            //验证权限 todo 数据量大的时候验证方式需要更换
            $rights = $this->rightService->select([['url', 'like', "%$value%"]],['id']);
            if (!$rights)  ApiUtil::normal(null, '权限记录不存在', ApiUtil::CODE_FAIL);
            //判断管理员是否有该权限
            $has_right = $this->roleRightLinkService->count(['role_id'=>$admin_info['role_id']],['right_id',$rights->column('id')]);
            if (!$has_right)  ApiUtil::normal( null, '你没有该权限', ApiUtil::CODE_FAIL);
        }
        //返回管理员信息
        return [
            'user_id' => $user_id,
            'admin_id' => $admin_info['id'],
            'role_range' => $admin_info['role']['range'],
        ];
    }
}
